FreeCalypso > hg > ueda-linux
view ueda/sverp/link.c @ 139:bf188727e606
donl-rename-parts reader: no tEDAx-style escapes
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 07 Sep 2020 04:25:11 +0000 |
parents | 7b4f78fcca08 |
children |
line wrap: on
line source
/* * ueda-sverp link pass */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "struct.h" extern struct module_def *glob_module_list, *top_module_def; extern int top_module_candidates; extern struct module_def *find_module_by_name(); static void toplevel_candidate(mod) struct module_def *mod; { top_module_candidates++; if (!top_module_def) top_module_def = mod; } static struct module_net_def * find_port_by_name(mod, portname) struct module_def *mod; register char *portname; { register struct module_net_def *n; for (n = mod->nets; n; n = n->next) if (!strcmp(n->name, portname)) break; if (n && n->is_port) return(n); else return(0); } static void handle_downport_range(mup, ins, conn) struct module_def *mup; struct module_def_subinst *ins; register struct connect_entry *conn; { register struct module_net_def *port; port = conn->down_portdef; if (!port->is_bus) { fprintf(stderr, "module %s line %d: mod %s port %s is not a bus, range spec is meaningless\n", mup->name, conn->src_lineno, ins->submod_name, port->name); exit(1); } if (port->bus_msb > port->bus_lsb) { if (conn->down_range_msb < conn->down_range_lsb) { error_reversed: fprintf(stderr, "module %s line %d: reversed range on bus port %s\n", mup->name, conn->src_lineno, port->name); exit(1); } if (conn->down_range_msb > port->bus_msb) { error_outofrange: fprintf(stderr, "module %s line %d: subrange on bus port %s exceeds full bus range\n", mup->name, conn->src_lineno, port->name); exit(1); } if (conn->down_range_lsb < port->bus_lsb) goto error_outofrange; conn->down_offset = port->bus_msb - conn->down_range_msb; conn->down_width = conn->down_range_msb - conn->down_range_lsb + 1; } else { if (conn->down_range_msb > conn->down_range_lsb) goto error_reversed; if (conn->down_range_msb < port->bus_msb) goto error_outofrange; if (conn->down_range_lsb > port->bus_lsb) goto error_outofrange; conn->down_offset = conn->down_range_msb - port->bus_msb; conn->down_width = conn->down_range_lsb - conn->down_range_msb + 1; } } static void connect_by_name(mup, ins) struct module_def *mup; register struct module_def_subinst *ins; { register struct connect_entry *conn; register struct module_net_def *port; for (conn = ins->connections; conn; conn = conn->next) { port = find_port_by_name(ins->submod_def, conn->down_portname); if (!port) { fprintf(stderr, "instance %s in module %s: lower module %s has no port named \"%s\"\n", ins->inst_name, mup->name, ins->submod_name, conn->down_portname); exit(1); } conn->down_portdef = port; if (conn->down_range_given) handle_downport_range(mup, ins, conn); else { conn->down_offset = 0; conn->down_width = port->bus_width; } } } static void connect_by_order(mup, ins) struct module_def *mup; register struct module_def_subinst *ins; { struct module_def *mdown; register struct module_net_def *port; register struct connect_entry *conn; mdown = ins->submod_def; if (ins->connect_by_order != mdown->nports) { fprintf(stderr, "instance %s in module %s: connect by order port count mismatch (%d ports, %d connections)\n", ins->inst_name, mup->name, mdown->nports, ins->connect_by_order); exit(1); } for (conn = ins->connections, port = mdown->nets; conn; conn = conn->next, port = port->next) { conn->down_portdef = port; conn->down_offset = 0; conn->down_width = port->bus_width; } } static void check_width_match(mup, ins) struct module_def *mup; struct module_def_subinst *ins; { register struct connect_entry *conn; for (conn = ins->connections; conn; conn = conn->next) if (conn->up_netdef && conn->up_width != conn->down_width) { fprintf(stderr, "module %s line %d: width mismatch on connection to port %s\n", mup->name, conn->src_lineno, conn->down_portdef->name); exit(1); } } static void linkpass_process_inst(mup, ins) struct module_def *mup; register struct module_def_subinst *ins; { register struct module_def *mdown; mdown = find_module_by_name(ins->submod_name); if (!mdown) { fprintf(stderr, "instance %s in module %s: lower module \"%s\" not found\n", ins->inst_name, mup->name, ins->submod_name); exit(1); } ins->submod_def = mdown; if (ins->connect_by_order) connect_by_order(mup, ins); else connect_by_name(mup, ins); check_width_match(mup, ins); } static void linkpass_process_mod(mod) struct module_def *mod; { register struct module_def_subinst *ins; for (ins = mod->subinst; ins; ins = ins->next) linkpass_process_inst(mod, ins); } link_pass() { register struct module_def *m; for (m = glob_module_list; m; m = m->next) { if (m->is_primitive) continue; if (!m->nports) toplevel_candidate(m); linkpass_process_mod(m); } }