Skip to content

Commit

Permalink
WIP: SDF file save / load to the disc.
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrej.ille committed Sep 6, 2024
1 parent 1e119ed commit 2128b24
Show file tree
Hide file tree
Showing 11 changed files with 327 additions and 136 deletions.
39 changes: 15 additions & 24 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "type.h"
#include "vlog/vlog-phase.h"
#include "sdf/sdf-phase.h"
#include "sdf/sdf-util.h"

#include <assert.h>
#include <ctype.h>
Expand Down Expand Up @@ -2488,36 +2489,26 @@ void analyse_file(const char *file, jit_t *jit, unit_registry_t *ur)
break;

case SOURCE_SDF:
{
#ifdef ENABLE_SDF
// TODO: Pass min-max spec
sdf_file_t *sdf_file = sdf_parse(0);
sdf_dump(sdf_file, 2);
#else
fatal("SDF not supported!");
#endif
}

break;
}
}

sdf_file_t* analyse_sdf_file(const char *file)
{
// TODO: Add support for compressed SDFs
{
sdf_file_t* sdf_file = sdf_parse(file, 0);
progress("analysed SDF file: %s", file);

input_from_file(file);
const char LOCAL *compiled_file = xasprintf("%s.compiled", file);
sdf_save_file(sdf_file, compiled_file);
sdf_file_free(sdf_file);
progress("wrote compiled SDF file to: %s", compiled_file);

#ifdef ENABLE_SDF
reset_sdf_parser();

// TODO: Pass min max spec!
return sdf_parse(0);
sdf_file = sdf_load_file(compiled_file);
progress("read compiled SDF file from: %s", compiled_file);
}
#else
fatal("SDF not supported!");
return NULL;
fatal("SDF not supported!");
return NULL;
#endif

break;
}
}

bool all_character_literals(type_t type)
Expand Down
1 change: 0 additions & 1 deletion src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ bool calculate_aggregate_bounds(tree_t expr, range_kind_t *kind,
type_t calculate_aggregate_subtype(tree_t expr);

void analyse_file(const char *file, jit_t *jit, unit_registry_t *ur);
sdf_file_t* analyse_sdf_file(const char *file);

void print_syntax(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
Expand Down
5 changes: 3 additions & 2 deletions src/nvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "vhpi/vhpi-util.h"
#include "vlog/vlog-node.h"
#include "vlog/vlog-phase.h"
#include "sdf/sdf-node.h"

#include <getopt.h>
#include <stdlib.h>
Expand Down Expand Up @@ -460,8 +461,8 @@ static int elaborate(int argc, char **argv, cmd_state_t *state)

#ifdef ENABLE_SDF
if (sdf_args != NULL) {
analyse_sdf_file(sdf_args);
progress("analysed SDF file: %s", sdf_args);
// TODO: Pass min-max spec to underlying sdf_parse somehow
analyse_file(sdf_args, NULL, NULL);
}
#endif

Expand Down
3 changes: 2 additions & 1 deletion src/sdf/Makemodule.am
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ lib_libnvc_a_SOURCES += \
if ENABLE_SDF
lib_libnvc_a_SOURCES += \
src/sdf/sdf-dump.c \
src/sdf/sdf-parse.c
src/sdf/sdf-parse.c \
src/sdf/sdf-util.c
endif

# AM_LFLAGS = -d
17 changes: 15 additions & 2 deletions src/sdf/sdf-node.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

static const imask_t has_map[S_LAST_NODE_KIND] = {
// S_DELAY_FILE
(I_SUBKIND | I_DECLS | I_STMTS),
(I_IDENT | I_SUBKIND | I_DECLS | I_STMTS),

// S_HEADER_ITEM
(I_SUBKIND | I_NUMBER | I_IDENT),
Expand Down Expand Up @@ -106,7 +106,7 @@ object_class_t sdf_object = {
.kind_text_map = kind_text_map,
.tag = OBJECT_TAG_SDF,
.last_kind = S_LAST_NODE_KIND,
.has_loc = true,
.has_loc = false,
.gc_roots = { S_DELAY_FILE },
.gc_num_roots = 1
};
Expand Down Expand Up @@ -574,3 +574,16 @@ unsigned sdf_exceptions(sdf_node_t s)
item_t *item = lookup_item(&sdf_object, s, I_CONTEXT);
return obj_array_count(item->obj_array);
}

object_t *sdf_to_object(sdf_node_t s)
{
return &(s->object);
}

sdf_node_t sdf_from_object(object_t *obj)
{
if (obj != NULL && obj->tag == OBJECT_TAG_SDF)
return container_of(obj, struct _sdf_node, object);
else
return NULL;
}
25 changes: 20 additions & 5 deletions src/sdf/sdf-node.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,23 @@ struct _sdf_file {
char hchar;
char hchar_other;

// Hierarchy -> Node list map
shash_t *hier_map;

// Cell name -> Node list map (for wildcards)
shash_t *name_map;
// hier_map: Hierarchy -> Cell map
// name_map: Cell name -> Cell map (for wildcards)
// Each cell is placed in only one of these two hash tables.
// Duplicities are prevented by looking up cells in the hash tables before
// adding the cell. Thus cells with equal:
// - hierarchy (INSTANCE [hierarchy])
// - cell name and wildcard (CELLNAME, INSTANCE *)
// are merged into single S_CELL object.
// TODO: Resolve location tracking. SDF standard says that information from
// SDF file should be annotated in order it is present in the SDF file.
// If there is a cell annotated due to cell_name and instance wildcard,
// and also annotated by cell with hierarchy entry, then it is currently
// not possible to figure out which one to apply earlier. This is because
// loc_t is invalid since it counts only until 1M lines! Maybe somehow
// tracking only line number ?
hash_t *hier_map;
hash_t *name_map;

// Mask of delays that are parsed:
// S_F_MIN_DELAYS, S_F_TYP_DELAYS, S_F_MAX_DELAYS
Expand Down Expand Up @@ -295,4 +307,7 @@ void sdf_add_exception(sdf_node_t s, sdf_node_t e);
unsigned sdf_exceptions(sdf_node_t s);
sdf_node_t sdf_exception(sdf_node_t s, unsigned int n);

object_t *sdf_to_object(sdf_node_t s);
sdf_node_t sdf_from_object(object_t *obj);

#endif // _SDF_NODE_H
112 changes: 37 additions & 75 deletions src/sdf/sdf-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "hash.h"
#include "sdf/sdf-node.h"
#include "sdf/sdf-phase.h"
#include "sdf/sdf-util.h"

#include <ctype.h>
#include <string.h>
Expand Down Expand Up @@ -108,8 +109,6 @@ static void _push_state(const rule_state_t *s);

#define BEGIN(s) BEGIN_WITH_HEAD(s, NULL)

#define CURRENT_LOC _diff_loc(&state.start_loc, &state.last_loc)

static inline void _pop_state(const rule_state_t *r)
{
#if TRACE_PARSE
Expand Down Expand Up @@ -305,18 +304,6 @@ static int _one_of(int dummy, ...)
}
}

static const loc_t *_diff_loc(const loc_t *start, const loc_t *end)
{
static loc_t result;

result = get_loc(start->first_line,
start->first_column,
end->first_line + end->line_delta,
end->first_column + end->column_delta,
start->file_ref);
return &result;
}

static ident_t error_marker(void)
{
return well_known(W_ERROR);
Expand All @@ -335,46 +322,6 @@ static inline bool is_next_tok_signed_number(void)
return scan(tINT, tREAL, tPLUS, tMINUS);
}

static void insert_sdf_cell(sdf_node_t cell)
{
assert(sdf_kind(cell) == S_CELL);
assert(sdf_has_ident(cell));

sdf_add_cell(sdf_file->root, cell);

const char *cell_instance = (sdf_has_ident2(cell)) ? istr(sdf_ident2(cell)) : NULL;
const char *cell_type = istr(sdf_ident(cell));

shash_t *hash;
const char *key;

// Hierarchy defined and not a wild-card -> Hash by hierarchy
if (cell_instance && strcmp(cell_instance, "*")) {
hash = sdf_file->hier_map;
key = cell_instance;
}

// Hierarchy not defined or a wild-card -> Has by cell type
else {
hash = sdf_file->name_map;
key = cell_type;
}

ptr_list_t *l = (ptr_list_t*)(shash_get(hash, key));

if (l == NULL)
l = (ptr_list_t*) xcalloc(sizeof(ptr_list_t));

shash_put(hash, key, l);

// TODO: Here it might be better to store only index of the cell in
// sdf_cells(ctx->root). At the time of adding the cell, the
// index is known. Then, if the root sdf_node is serialized together
// with the hash table, we are able to deserialize back the hash
// table with valid data pointing into the list of cells!
list_add(l, cell);
}

#define EPSILON 0.0000000000001

static bool doubles_equal(double a, double b)
Expand Down Expand Up @@ -2410,7 +2357,7 @@ static void p_del_spec(sdf_node_t cell)
consume(tRPAREN);
}

static sdf_node_t p_cell(void)
static void p_cell(void)
{
// cell ::=
// ( CELL celltype cell_instance { timing_spec } )
Expand All @@ -2425,20 +2372,39 @@ static sdf_node_t p_cell(void)
consume(tLPAREN);
consume(tCELL);

sdf_node_t cell = sdf_new(S_CELL);

// celltype
consume(tLPAREN);
consume(tCELLTYPE);

ident_t cell_type = p_qstring();
sdf_set_ident(cell, cell_type);

consume(tRPAREN);

// cell_instance
ident_t hier = p_cell_instance();
sdf_set_ident2(cell, hier);

sdf_node_t cell = sdf_get_cell_from_hash(sdf_file, hier, cell_type);
if (cell == NULL) {
cell = sdf_new(S_CELL);
sdf_set_ident(cell, cell_type);
sdf_set_ident2(cell, hier);
sdf_add_cell(sdf_file->root, cell);
sdf_put_cell_to_hash(sdf_file, cell, sdf_cells(sdf_file->root));
}
else if (!icmp(hier, "*")) {
// If a cell with equal hierarchy exists, it should be the
// same celltype, otherwise the written SDF file does not
// really describe consistent design...
ident_t id = sdf_ident(cell);
if (ident_compare(id, cell_type)) {
const char *orig_hier = (sdf_has_ident2(cell)) ?
istr(sdf_ident2(cell)) : "";

warn_at(&state.last_loc, "SDF cell with INSTANCE: %s was already"
"defined in the SDF file with CELLTYPE: %s",
istr(id), orig_hier);
}
}

// { timing_spec }
int tok = peek_nth(2);
Expand All @@ -2463,8 +2429,6 @@ static sdf_node_t p_cell(void)
}

consume(tRPAREN);

return cell;
}

static void p_timescale(void)
Expand Down Expand Up @@ -2723,7 +2687,7 @@ static void p_sdf_header(void)
p_timescale();
}

static sdf_file_t* p_delay_file(sdf_flags_t min_max_spec)
static sdf_file_t* p_delay_file(const char *file, sdf_flags_t min_max_spec)
{
// delay_file ::=
// ( DELAYFILE sdf_header cell { cell } )
Expand All @@ -2733,18 +2697,18 @@ static sdf_file_t* p_delay_file(sdf_flags_t min_max_spec)
consume(tLPAREN);
consume(tDELAYFILE);

sdf_file = xcalloc(sizeof(struct _sdf_file));
sdf_file->hier_map = shash_new(4096);
sdf_file->name_map = shash_new(1024);
sdf_file = sdf_file_new(16384, 256);

sdf_file->root = sdf_new(S_DELAY_FILE);
sdf_file->hchar = '.';
sdf_file->min_max_spec = min_max_spec;
sdf_file->root = sdf_new(S_DELAY_FILE);

sdf_set_ident(sdf_file->root, ident_new(basename(file)));

p_sdf_header();

while (peek_nth(2) == tCELL)
insert_sdf_cell(p_cell());
p_cell();

consume(tRPAREN);

Expand All @@ -2755,23 +2719,21 @@ static sdf_file_t* p_delay_file(sdf_flags_t min_max_spec)
// Public API
///////////////////////////////////////////////////////////////////////////////

sdf_file_t* sdf_parse(sdf_flags_t min_max_spec)
sdf_file_t* sdf_parse(const char *file, sdf_flags_t min_max_spec)
{
make_new_arena();

scan_as_sdf();

reset_sdf_parser();

if (peek() == tEOF)
return NULL;

return p_delay_file(min_max_spec);
}
make_new_arena();

void sdf_free(sdf_file_t *sdf_file)
{
// TODO: Walk the hash maps and free both hmap and cmap!
return p_delay_file(file, min_max_spec);
}

void reset_sdf_parser(void)
{
state.tokenq_head = state.tokenq_tail = 0;
}
8 changes: 6 additions & 2 deletions src/sdf/sdf-phase.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@
#include "common.h"
#include "hash.h"

sdf_file_t* sdf_parse(sdf_flags_t min_max_spec);
void sdf_free(sdf_file_t *sdf);
sdf_file_t* sdf_parse(const char *file, sdf_flags_t min_max_spec);
void sdf_dump(sdf_file_t *sdf, int indent);

void sdf_save_file(sdf_file_t *sdf_file, const char *file);
sdf_file_t* sdf_load_file(const char *file);

void sdf_free(sdf_file_t *sdf);

#endif // _SDF_PHASE_H
Loading

0 comments on commit 2128b24

Please sign in to comment.