summaryrefslogblamecommitdiff
path: root/csim/load.c
blob: 485a74367022f382819d7e71dbe43f8c2cec329e (plain) (tree)
1
2
3
4
5
6
7
  


                    
 

                                                      





                   

                   












                                        
                                              





                                       
                      

                                                                      
 
                                              
                          

                                                    

                                                          






                                                 
 

                                             






















































































                                                                                                                   
                                                 






































                                                                                                                           
 
/*
    Système Digital
    2013-2014
    Alex AUVOLAT

    load.c  Code for loading dumbed-down netlist files
            (no parsing of .net files !!)
*/

#include <stdlib.h>

#include "sim.h"

t_rom *roms = NULL;

void eat_comment(FILE *file) {
    while (1) {
        char c = fgetc(file);
        if (isspace(c)) continue;
        if (c == '#') {
            while (fgetc(file) != '\n');
            continue;
        }
        ungetc(c, file);
        break;
    }
}

void add_rom(const char *prefix, FILE *file) {
    int i;

    t_rom *rom = malloc(sizeof(t_rom));
    rom->prefix = prefix;

    // Load ROM file
    eat_comment(file);
    fscanf(file, "%d %d\n", &(rom->words_defined), &(rom->word_size));
    rom->data = malloc(rom->words_defined * sizeof(t_value));

    for (i = 0; i < rom->words_defined; i++) {
        eat_comment(file);
        if (fscanf(file, "/%lu", &(rom->data[i]))) {
            // ok, value is read
        } else if (fscanf(file, "x%x", &(rom->data[i]))) {
            // ok, value is read
        } else {
            rom->data[i] = read_bool(file, NULL);
        }
    }

    rom->next = roms;
    roms = rom;
}

t_program *load_dumb_netlist (FILE *stream) {
    int i, j, as, ws;
    t_rom *r;

    // let us suppose that the input to be read is well-formed.
    t_program *p = malloc(sizeof(t_program));
    
    // Read variable list, with sizes and identifiers
    fscanf(stream, "%d ", &(p->n_vars));
    p->vars = malloc(p->n_vars * sizeof(t_variable));
    
    for (i = 0; i < p->n_vars; i++) {
        fscanf(stream, "%d ", &(p->vars[i].size));
        for(j = 0; j < p->vars[i].size; j++) {
            p->vars[i].mask = (p->vars[i].mask << 1) | 1;
        }

        p->vars[i].name = malloc(42);   // let's bet that the name of a variable will never be longer than 42 chars
        fscanf(stream, "%s\n", p->vars[i].name);

        if (p->vars[i].size >= 8*sizeof(t_value)) {
            fprintf(stderr, "Warning: variable %s might be too big for machine integers.\n", p->vars[i].name);
        }
    }

    // read input list
    fscanf(stream, "%d ", &(p->n_inputs));
    p->inputs = malloc(p->n_inputs * sizeof(t_id));
    for (i = 0; i < p->n_inputs; i++) {
        fscanf(stream, "%d ", &(p->inputs[i]));
    }
    // read output list
    fscanf(stream, "%d ", &(p->n_outputs));
    p->outputs = malloc(p->n_outputs * sizeof(t_id));
    for (i = 0; i < p->n_outputs; i++) {
        fscanf(stream, "%d ", &(p->outputs[i]));
    }

    // read register list
    fscanf(stream, "%d", &(p->n_regs));
    p->regs = malloc(p->n_regs * sizeof(t_reg));
    for (i = 0; i < p->n_regs; i++) {
        fscanf(stream, "%d %d\n", &(p->regs[i].dest), &(p->regs[i].source));
    }
    // read RAM list
    fscanf(stream, "%d", &(p->n_rams));
    p->rams = malloc(p->n_rams * sizeof(t_ram));
    for (i = 0; i < p->n_rams; i++) {
        fscanf(stream, "%d %d %d %d %d\n",
            &(p->rams[i].addr_size),
            &(p->rams[i].word_size),
            &(p->rams[i].write_enable),
            &(p->rams[i].write_addr), &(p->rams[i].data));
    }

    // read equation list
    fscanf(stream, "%d ", &(p->n_eqs));
    p->eqs = malloc(p->n_eqs * sizeof(t_equation));
    for (i = 0; i < p->n_eqs; i++) {
        fscanf(stream, "%d ", &(p->eqs[i].dest_var));
        fscanf(stream, "%d ", &(p->eqs[i].type));
        switch (p->eqs[i].type) {
            case C_COPY:
                fscanf(stream, "%d ", &(p->eqs[i].Copy.a));
                break;
            case C_NOT:
                fscanf(stream, "%d ", &(p->eqs[i].Not.a));
                break;
            case C_BINOP:
                fscanf(stream, "%d %d %d ",
                    &(p->eqs[i].Binop.op),
                    &(p->eqs[i].Binop.a),
                    &(p->eqs[i].Binop.b));
                break;
            case C_MUX:
                fscanf(stream, "%d %d %d ",
                    &(p->eqs[i].Mux.a),
                    &(p->eqs[i].Mux.b),
                    &(p->eqs[i].Mux.c));
                break;
            case C_ROM:
                fscanf(stream, "%d %d %d ",
                    &as, &ws,
                    &(p->eqs[i].Rom.read_addr));
                p->eqs[i].Rom.rom = NULL;
                // find corresponding ROM
                for (r = roms; r != NULL; r = r->next) {
                    if (is_prefix(r->prefix, p->vars[p->eqs[i].dest_var].name)) {
                        if (r->word_size == ws) {
                            p->eqs[i].Rom.rom = r;
                            break;
                        } else {
                            fprintf(stderr,
                                "Error: ROM prefixed by '%s' does not have size corresponding to variable that uses it.\n",
                                r->prefix);
                        }
                    }
                }
                if (p->eqs[i].Rom.rom == NULL)
                    fprintf(stderr, "Warning: ROM variable '%s' has no ROM data.\n",
                        p->vars[p->eqs[i].dest_var].name);
                break;
            case C_CONCAT:
                fscanf(stream, "%d %d ",
                    &(p->eqs[i].Concat.a),
                    &(p->eqs[i].Concat.b));
                p->eqs[i].Concat.shift = p->vars[p->eqs[i].Concat.a].size;
                break;
            case C_SLICE:
                fscanf(stream, "%d %d %d ",
                    &(p->eqs[i].Slice.begin),
                    &(p->eqs[i].Slice.end),
                    &(p->eqs[i].Slice.source));
                break;
            case C_SELECT:
                fscanf(stream, "%d %d ",
                    &(p->eqs[i].Select.i),
                    &(p->eqs[i].Select.source));
                break;
            case C_READRAM:
                fscanf(stream, "%d %d ",
                    &(p->eqs[i].ReadRAM.ram_id),
                    &(p->eqs[i].ReadRAM.source));
                break;
        }
    }

    return p;
}