mirror of https://github.com/YosysHQ/abc.git
Changes to "read_jsonc".
This commit is contained in:
parent
58023c97b7
commit
60f52cc082
|
|
@ -1890,7 +1890,8 @@ usage:
|
|||
***********************************************************************/
|
||||
int IoCommandReadJsonc( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern int Jsonc_ReadTest( char * pFileName );
|
||||
extern Abc_Ntk_t * Jsonc_ReadNetwork( char * pFileName );
|
||||
Abc_Ntk_t * pNtk;
|
||||
char * pFileName;
|
||||
FILE * pFile;
|
||||
int c;
|
||||
|
|
@ -1920,7 +1921,11 @@ int IoCommandReadJsonc( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
}
|
||||
fclose( pFile );
|
||||
|
||||
Jsonc_ReadTest( pFileName );
|
||||
pNtk = Jsonc_ReadNetwork( pFileName );
|
||||
if ( pNtk == NULL )
|
||||
return 1;
|
||||
Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
|
||||
Abc_FrameClearVerifStatus( pAbc );
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
|
|
@ -4607,4 +4612,3 @@ usage:
|
|||
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,14 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ioAbc.h"
|
||||
#include "base/abc/abc.h"
|
||||
#include "base/main/main.h"
|
||||
#include "map/mio/mio.h"
|
||||
#include "ioAbc.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
|
|
@ -45,38 +47,50 @@ typedef enum {
|
|||
} json_type_t;
|
||||
|
||||
// Core structure: stores offset and length in the original string
|
||||
typedef struct {
|
||||
uint32_t offset; // Offset in the JSON string
|
||||
uint32_t length; // Length of this value
|
||||
json_type_t type; // Type of JSON value
|
||||
typedef struct json_value_t_ {
|
||||
uint32_t offset; // Offset in the JSON string
|
||||
uint32_t length; // Length of this value
|
||||
json_type_t type; // Type of JSON value
|
||||
uint32_t container; // Index of the container if this is an object/array
|
||||
} json_value_t;
|
||||
|
||||
// Key-value pair for objects
|
||||
typedef struct {
|
||||
json_value_t key; // Key (always a string)
|
||||
json_value_t value; // Associated value
|
||||
typedef struct json_pair_t_ {
|
||||
json_value_t key; // Key (always a string)
|
||||
json_value_t value; // Associated value
|
||||
} json_pair_t;
|
||||
|
||||
// Dynamic array for storing pairs (objects) or values (arrays)
|
||||
typedef struct {
|
||||
typedef struct json_container_t_ {
|
||||
union {
|
||||
json_pair_t *pairs; // For objects
|
||||
json_value_t *values; // For arrays
|
||||
} data;
|
||||
uint32_t count; // Number of elements
|
||||
uint32_t capacity; // Allocated capacity
|
||||
uint32_t count; // Number of elements
|
||||
uint32_t capacity; // Allocated capacity
|
||||
} json_container_t;
|
||||
|
||||
// Main JSON structure
|
||||
typedef struct {
|
||||
char *str; // The original JSON string
|
||||
uint32_t str_len; // Length of the string
|
||||
json_value_t root; // Root element
|
||||
json_container_t *containers; // Array of containers
|
||||
uint32_t container_count; // Number of containers
|
||||
uint32_t container_capacity; // Allocated capacity
|
||||
typedef struct json_t_ {
|
||||
char *str; // The original JSON string
|
||||
uint32_t str_len; // Length of the string
|
||||
json_value_t root; // Root element
|
||||
json_container_t *containers; // Array of containers
|
||||
uint32_t container_count; // Number of containers
|
||||
uint32_t container_capacity; // Allocated capacity
|
||||
} json_t;
|
||||
|
||||
// Creation / destruction
|
||||
json_t * json_create(void);
|
||||
void json_destroy(json_t *json);
|
||||
bool json_load_file(json_t *json, const char *filename);
|
||||
|
||||
// Debug/printing helpers
|
||||
void json_print(json_t *json, FILE *fp);
|
||||
void json_print_value(json_t *json, json_value_t val, FILE *fp, int indent, bool format);
|
||||
void json_print_string(json_t *json, json_value_t val, FILE *fp);
|
||||
void json_debug_value(json_t *json, json_value_t val, int indent);
|
||||
|
||||
// Function prototypes
|
||||
json_t* json_create(void);
|
||||
void json_destroy(json_t *json);
|
||||
|
|
@ -93,6 +107,12 @@ void json_print_value(json_t *json, json_value_t val, FILE *fp, int indent, bool
|
|||
void json_print_string(json_t *json, json_value_t val, FILE *fp);
|
||||
void json_debug_value(json_t *json, json_value_t val, int indent);
|
||||
|
||||
extern Abc_Ntk_t * Abc_NtkFromMiniMapping( int * pArray );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Create a new JSON structure
|
||||
json_t* json_create(void) {
|
||||
json_t *json = (json_t*)calloc(1, sizeof(json_t));
|
||||
|
|
@ -185,6 +205,7 @@ json_container_t* json_add_container(json_t *json) {
|
|||
// Parse a JSON string
|
||||
json_value_t json_parse_string(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
val.container = UINT32_MAX;
|
||||
val.type = JSON_STRING;
|
||||
val.offset = *pos;
|
||||
|
||||
|
|
@ -203,6 +224,7 @@ json_value_t json_parse_string(json_t *json, uint32_t *pos) {
|
|||
// Parse a JSON number
|
||||
json_value_t json_parse_number(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
val.container = UINT32_MAX;
|
||||
val.type = JSON_NUMBER;
|
||||
val.offset = *pos;
|
||||
|
||||
|
|
@ -223,6 +245,7 @@ json_value_t json_parse_number(json_t *json, uint32_t *pos) {
|
|||
// Parse a JSON object
|
||||
json_value_t json_parse_object(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
val.container = UINT32_MAX;
|
||||
val.type = JSON_OBJECT;
|
||||
val.offset = *pos;
|
||||
|
||||
|
|
@ -230,6 +253,8 @@ json_value_t json_parse_object(json_t *json, uint32_t *pos) {
|
|||
|
||||
json_container_t *container = json_add_container(json);
|
||||
if (!container) return val;
|
||||
val.container = json->container_count - 1;
|
||||
container = json->containers + val.container;
|
||||
|
||||
container->capacity = 8;
|
||||
container->data.pairs = (json_pair_t*)calloc(container->capacity, sizeof(json_pair_t));
|
||||
|
|
@ -249,6 +274,7 @@ json_value_t json_parse_object(json_t *json, uint32_t *pos) {
|
|||
json_value_t value = json_parse_value(json, pos);
|
||||
|
||||
// Add pair to container
|
||||
container = json->containers + val.container;
|
||||
if (container->count >= container->capacity) {
|
||||
uint32_t new_capacity = container->capacity * 2;
|
||||
json_pair_t *new_pairs = (json_pair_t*)realloc(
|
||||
|
|
@ -278,6 +304,7 @@ json_value_t json_parse_object(json_t *json, uint32_t *pos) {
|
|||
// Parse a JSON array
|
||||
json_value_t json_parse_array(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
val.container = UINT32_MAX;
|
||||
val.type = JSON_ARRAY;
|
||||
val.offset = *pos;
|
||||
|
||||
|
|
@ -285,6 +312,8 @@ json_value_t json_parse_array(json_t *json, uint32_t *pos) {
|
|||
|
||||
json_container_t *container = json_add_container(json);
|
||||
if (!container) return val;
|
||||
val.container = json->container_count - 1;
|
||||
container = json->containers + val.container;
|
||||
|
||||
container->capacity = 8;
|
||||
container->data.values = (json_value_t*)calloc(container->capacity, sizeof(json_value_t));
|
||||
|
|
@ -297,6 +326,7 @@ json_value_t json_parse_array(json_t *json, uint32_t *pos) {
|
|||
json_value_t value = json_parse_value(json, pos);
|
||||
|
||||
// Add value to container
|
||||
container = json->containers + val.container;
|
||||
if (container->count >= container->capacity) {
|
||||
uint32_t new_capacity = container->capacity * 2;
|
||||
json_value_t *new_values = (json_value_t*)realloc(
|
||||
|
|
@ -325,6 +355,7 @@ json_value_t json_parse_array(json_t *json, uint32_t *pos) {
|
|||
// Parse any JSON value
|
||||
json_value_t json_parse_value(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
val.container = UINT32_MAX;
|
||||
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
|
||||
|
|
@ -342,18 +373,21 @@ json_value_t json_parse_value(json_t *json, uint32_t *pos) {
|
|||
val.type = JSON_NULL;
|
||||
val.offset = *pos;
|
||||
val.length = 4;
|
||||
val.container = UINT32_MAX;
|
||||
*pos += 4;
|
||||
return val;
|
||||
} else if (c == 't') {
|
||||
val.type = JSON_BOOL;
|
||||
val.offset = *pos;
|
||||
val.length = 4;
|
||||
val.container = UINT32_MAX;
|
||||
*pos += 4;
|
||||
return val;
|
||||
} else if (c == 'f') {
|
||||
val.type = JSON_BOOL;
|
||||
val.offset = *pos;
|
||||
val.length = 5;
|
||||
val.container = UINT32_MAX;
|
||||
*pos += 5;
|
||||
return val;
|
||||
} else if ((c >= '0' && c <= '9') || c == '-') {
|
||||
|
|
@ -397,6 +431,7 @@ bool json_load_file(json_t *json, const char *filename) {
|
|||
|
||||
json->str[file_size] = '\0';
|
||||
json->str_len = (uint32_t)file_size;
|
||||
json->container_count = 0;
|
||||
|
||||
// Parse JSON
|
||||
uint32_t pos = 0;
|
||||
|
|
@ -442,24 +477,8 @@ void json_print_string(json_t *json, json_value_t val, FILE *fp) {
|
|||
fputc('"', fp);
|
||||
}
|
||||
|
||||
// Find the container index for a given value
|
||||
static int find_container_index(json_t *json, json_value_t val) {
|
||||
static int last_container = 0;
|
||||
|
||||
// Check if it's an object or array
|
||||
if (val.type == JSON_OBJECT || val.type == JSON_ARRAY) {
|
||||
int index = last_container++;
|
||||
if (index < json->container_count) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Print a JSON value recursively
|
||||
void json_print_value(json_t *json, json_value_t val, FILE *fp, int indent, bool format) {
|
||||
static int container_index = 0;
|
||||
|
||||
switch (val.type) {
|
||||
case JSON_NULL:
|
||||
fprintf(fp, "null");
|
||||
|
|
@ -486,8 +505,8 @@ void json_print_value(json_t *json, json_value_t val, FILE *fp, int indent, bool
|
|||
case JSON_ARRAY: {
|
||||
fputc('[', fp);
|
||||
|
||||
if (container_index < json->container_count) {
|
||||
json_container_t *container = &json->containers[container_index++];
|
||||
if (val.container < json->container_count) {
|
||||
json_container_t *container = &json->containers[val.container];
|
||||
|
||||
for (uint32_t i = 0; i < container->count; i++) {
|
||||
if (format) {
|
||||
|
|
@ -516,8 +535,8 @@ void json_print_value(json_t *json, json_value_t val, FILE *fp, int indent, bool
|
|||
case JSON_OBJECT: {
|
||||
fputc('{', fp);
|
||||
|
||||
if (container_index < json->container_count) {
|
||||
json_container_t *container = &json->containers[container_index++];
|
||||
if (val.container < json->container_count) {
|
||||
json_container_t *container = &json->containers[val.container];
|
||||
|
||||
for (uint32_t i = 0; i < container->count; i++) {
|
||||
if (format) {
|
||||
|
|
@ -549,7 +568,6 @@ void json_print_value(json_t *json, json_value_t val, FILE *fp, int indent, bool
|
|||
|
||||
// Print the entire JSON to a file
|
||||
void json_print(json_t *json, FILE *fp) {
|
||||
// Reset the static container index in json_print_value
|
||||
json_print_value(json, json->root, fp, 0, true);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
|
@ -722,7 +740,6 @@ void Jsonc_WriteTest( Abc_Ntk_t * p, char * pFileName )
|
|||
fprintf( pFile, " }%s\n", Mio_PinReadNext(pPin) ? "," : "" );
|
||||
}
|
||||
fprintf( pFile, " }\n" );
|
||||
//fprintf( pFile, " ]\n" );
|
||||
fprintf( pFile, " }%s\n", ++Counter == Total ? "" : "," );
|
||||
}
|
||||
Abc_NtkForEachPo( p, pObj, i )
|
||||
|
|
@ -749,6 +766,443 @@ void Jsonc_WriteTest( Abc_Ntk_t * p, char * pFileName )
|
|||
Vec_PtrFree( vNodes );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static json_container_t * Jsonc_GetContainer( json_t * pJson, json_value_t value )
|
||||
{
|
||||
if ( value.container == UINT32_MAX )
|
||||
return NULL;
|
||||
if ( value.container >= pJson->container_count )
|
||||
return NULL;
|
||||
return pJson->containers + value.container;
|
||||
}
|
||||
static int Jsonc_StringEqual( json_t * pJson, json_value_t value, const char * pStr )
|
||||
{
|
||||
uint32_t Len;
|
||||
if ( value.type != JSON_STRING || value.length < 2 )
|
||||
return 0;
|
||||
Len = value.length - 2;
|
||||
return strlen(pStr) == Len && strncmp( pJson->str + value.offset + 1, pStr, Len ) == 0;
|
||||
}
|
||||
static char * Jsonc_StringDup( json_t * pJson, json_value_t value )
|
||||
{
|
||||
char * pRes;
|
||||
uint32_t i, Len;
|
||||
if ( value.type != JSON_STRING || value.length < 2 )
|
||||
return NULL;
|
||||
Len = value.length - 2;
|
||||
pRes = ABC_ALLOC( char, Len + 1 );
|
||||
for ( i = 0; i < Len; i++ )
|
||||
{
|
||||
char c = pJson->str[value.offset + 1 + i];
|
||||
if ( c == '\\' && i + 1 < Len )
|
||||
{
|
||||
i++;
|
||||
c = pJson->str[value.offset + 1 + i];
|
||||
}
|
||||
pRes[i] = c;
|
||||
}
|
||||
pRes[Len] = '\0';
|
||||
return pRes;
|
||||
}
|
||||
static int Jsonc_ParseInt( json_t * pJson, json_value_t value, int * pResult )
|
||||
{
|
||||
char * pBuffer, * pEnd;
|
||||
uint32_t Len;
|
||||
long Temp;
|
||||
if ( value.type != JSON_NUMBER )
|
||||
return 0;
|
||||
Len = value.length;
|
||||
pBuffer = ABC_ALLOC( char, Len + 1 );
|
||||
memcpy( pBuffer, pJson->str + value.offset, Len );
|
||||
pBuffer[Len] = '\0';
|
||||
Temp = strtol( pBuffer, &pEnd, 10 );
|
||||
ABC_FREE( pBuffer );
|
||||
if ( pEnd == NULL || pEnd == pBuffer )
|
||||
return 0;
|
||||
*pResult = (int)Temp;
|
||||
return 1;
|
||||
}
|
||||
static json_value_t * Jsonc_ObjectLookup( json_t * pJson, json_value_t object, const char * pKey )
|
||||
{
|
||||
json_container_t * pCont;
|
||||
uint32_t i;
|
||||
if ( object.type != JSON_OBJECT )
|
||||
return NULL;
|
||||
pCont = Jsonc_GetContainer( pJson, object );
|
||||
if ( pCont == NULL )
|
||||
return NULL;
|
||||
for ( i = 0; i < pCont->count; i++ )
|
||||
if ( Jsonc_StringEqual( pJson, pCont->data.pairs[i].key, pKey ) )
|
||||
return &pCont->data.pairs[i].value;
|
||||
return NULL;
|
||||
}
|
||||
static Vec_Int_t * Jsonc_NameCounts( Vec_Ptr_t * vBases, Vec_Int_t ** pvBaseIds )
|
||||
{
|
||||
Abc_Nam_t * pNames;
|
||||
Vec_Int_t * vCounts, * vBaseIds;
|
||||
char * pBase;
|
||||
int i, Id;
|
||||
pNames = Abc_NamStart( Vec_PtrSize(vBases) + 1, 24 );
|
||||
vCounts = Vec_IntAlloc( Vec_PtrSize(vBases) + 1 );
|
||||
vBaseIds = Vec_IntAlloc( Vec_PtrSize(vBases) + 1 );
|
||||
Vec_IntFillExtra( vCounts, 1, 0 );
|
||||
Vec_PtrForEachEntry( char *, vBases, pBase, i )
|
||||
{
|
||||
int fFound;
|
||||
Id = Abc_NamStrFindOrAdd( pNames, pBase, &fFound );
|
||||
Vec_IntFillExtra( vCounts, Id + 1, 0 );
|
||||
Vec_IntAddToEntry( vCounts, Id, 1 );
|
||||
Vec_IntPush( vBaseIds, Id );
|
||||
}
|
||||
Abc_NamDeref( pNames );
|
||||
*pvBaseIds = vBaseIds;
|
||||
return vCounts;
|
||||
}
|
||||
static void Jsonc_AppendName( Vec_Str_t * vNames, const char * pBase, int Bit, int fUseBit )
|
||||
{
|
||||
int nSize = (int)strlen(pBase ? pBase : "") + 32;
|
||||
char * pBuffer = ABC_ALLOC( char, nSize );
|
||||
if ( fUseBit )
|
||||
snprintf( pBuffer, nSize, "%s[%d]", pBase ? pBase : "", Bit );
|
||||
else
|
||||
snprintf( pBuffer, nSize, "%s", pBase ? pBase : "" );
|
||||
Vec_StrPrintStr( vNames, pBuffer );
|
||||
Vec_StrPush( vNames, '\0' );
|
||||
ABC_FREE( pBuffer );
|
||||
}
|
||||
static void Jsonc_AppendPortNames( Vec_Str_t * vNames, Vec_Ptr_t * vBases, Vec_Int_t * vBits )
|
||||
{
|
||||
Vec_Int_t * vCounts, * vBaseIds;
|
||||
char * pBase;
|
||||
int i, Bit, Count;
|
||||
vCounts = Jsonc_NameCounts( vBases, &vBaseIds );
|
||||
Vec_PtrForEachEntry( char *, vBases, pBase, i )
|
||||
{
|
||||
Bit = Vec_IntEntry( vBits, i );
|
||||
Count = Vec_IntEntry( vCounts, Vec_IntEntry( vBaseIds, i ) );
|
||||
Jsonc_AppendName( vNames, pBase, Bit, Bit != 0 || Count > 1 );
|
||||
}
|
||||
Vec_IntFree( vCounts );
|
||||
Vec_IntFree( vBaseIds );
|
||||
}
|
||||
static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * pLib, char ** ppDesignName )
|
||||
{
|
||||
Vec_Ptr_t * vPiBases = NULL, * vPoBases = NULL;
|
||||
Vec_Int_t * vPiBits = NULL, * vPoBits = NULL;
|
||||
Vec_Int_t * vNodeMap = NULL, * vGateIdx = NULL, * vPoIdx = NULL;
|
||||
Vec_Int_t * vMapping = NULL, * vPoDrivers = NULL;
|
||||
Vec_Str_t * vNames = NULL;
|
||||
json_container_t * pNodes;
|
||||
json_value_t * pTemp;
|
||||
char * pBase;
|
||||
int i, k, nCis = 0, nNodes = 0, nCos = 0;
|
||||
int fSuccess = 0;
|
||||
if ( ppDesignName )
|
||||
*ppDesignName = NULL;
|
||||
if ( pLib == NULL )
|
||||
{
|
||||
printf( "Genlib library is not available.\n" );
|
||||
return NULL;
|
||||
}
|
||||
if ( pJson->root.type != JSON_OBJECT )
|
||||
{
|
||||
printf( "JSONC root should be an object.\n" );
|
||||
return NULL;
|
||||
}
|
||||
pTemp = Jsonc_ObjectLookup( pJson, pJson->root, "name" );
|
||||
if ( pTemp && ppDesignName && pTemp->type == JSON_STRING )
|
||||
*ppDesignName = Jsonc_StringDup( pJson, *pTemp );
|
||||
pTemp = Jsonc_ObjectLookup( pJson, pJson->root, "nodes" );
|
||||
if ( pTemp == NULL || pTemp->type != JSON_ARRAY )
|
||||
{
|
||||
printf( "JSONC file is missing top-level \"nodes\" array.\n" );
|
||||
return NULL;
|
||||
}
|
||||
pNodes = Jsonc_GetContainer( pJson, *pTemp );
|
||||
if ( pNodes == NULL )
|
||||
{
|
||||
printf( "Internal JSONC structure is incomplete.\n" );
|
||||
return NULL;
|
||||
}
|
||||
vNodeMap = Vec_IntStartFull( pNodes->count );
|
||||
vGateIdx = Vec_IntAlloc( pNodes->count );
|
||||
vPoIdx = Vec_IntAlloc( pNodes->count );
|
||||
vPiBases = Vec_PtrAlloc( pNodes->count );
|
||||
vPiBits = Vec_IntAlloc( pNodes->count );
|
||||
vPoBases = Vec_PtrAlloc( pNodes->count );
|
||||
vPoBits = Vec_IntAlloc( pNodes->count );
|
||||
// first pass: collect object types and names
|
||||
for ( i = 0; i < (int)pNodes->count; i++ )
|
||||
{
|
||||
json_value_t Node = pNodes->data.values[i];
|
||||
json_value_t * pType = Jsonc_ObjectLookup( pJson, Node, "type" );
|
||||
json_value_t * pName = Jsonc_ObjectLookup( pJson, Node, "name" );
|
||||
json_value_t * pBit = Jsonc_ObjectLookup( pJson, Node, "bit" );
|
||||
int Bit = 0;
|
||||
if ( pType == NULL || pType->type != JSON_STRING )
|
||||
{
|
||||
printf( "Node %d does not have a valid \"type\" field.\n", i );
|
||||
goto cleanup;
|
||||
}
|
||||
if ( pBit && !Jsonc_ParseInt( pJson, *pBit, &Bit ) )
|
||||
{
|
||||
printf( "Node %d has an invalid \"bit\" field.\n", i );
|
||||
goto cleanup;
|
||||
}
|
||||
if ( Jsonc_StringEqual( pJson, *pType, "pi" ) )
|
||||
{
|
||||
Vec_IntWriteEntry( vNodeMap, i, nCis++ );
|
||||
pBase = Jsonc_StringDup( pJson, pName ? *pName : *pType );
|
||||
if ( pBase == NULL )
|
||||
{
|
||||
printf( "Primary input %d is missing a name.\n", i );
|
||||
goto cleanup;
|
||||
}
|
||||
Vec_PtrPush( vPiBases, pBase );
|
||||
Vec_IntPush( vPiBits, Bit );
|
||||
}
|
||||
else if ( Jsonc_StringEqual( pJson, *pType, "instance" ) )
|
||||
{
|
||||
Vec_IntPush( vGateIdx, i );
|
||||
nNodes++;
|
||||
}
|
||||
else if ( Jsonc_StringEqual( pJson, *pType, "PO" ) || Jsonc_StringEqual( pJson, *pType, "po" ) )
|
||||
{
|
||||
Vec_IntPush( vPoIdx, i );
|
||||
nCos++;
|
||||
pBase = Jsonc_StringDup( pJson, pName ? *pName : *pType );
|
||||
if ( pBase == NULL )
|
||||
{
|
||||
printf( "Primary output %d is missing a name.\n", i );
|
||||
goto cleanup;
|
||||
}
|
||||
Vec_PtrPush( vPoBases, pBase );
|
||||
Vec_IntPush( vPoBits, Bit );
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "Node %d has unsupported type.\n", i );
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
// assign IDs to internal nodes
|
||||
for ( i = 0; i < Vec_IntSize(vGateIdx); i++ )
|
||||
Vec_IntWriteEntry( vNodeMap, Vec_IntEntry(vGateIdx, i), nCis + i );
|
||||
// allocate storage for mapping
|
||||
vMapping = Vec_IntAlloc( 4 + nNodes * 4 + nCos + 10 );
|
||||
vNames = Vec_StrAlloc( 1024 );
|
||||
vPoDrivers = Vec_IntAlloc( nCos );
|
||||
Vec_IntPush( vMapping, nCis );
|
||||
Vec_IntPush( vMapping, nCos );
|
||||
Vec_IntPush( vMapping, nNodes );
|
||||
Vec_IntPush( vMapping, 0 ); // flops
|
||||
// second pass: build nodes and POs
|
||||
for ( i = 0; i < (int)pNodes->count; i++ )
|
||||
{
|
||||
json_value_t Node = pNodes->data.values[i];
|
||||
json_value_t * pType = Jsonc_ObjectLookup( pJson, Node, "type" );
|
||||
if ( Jsonc_StringEqual( pJson, *pType, "instance" ) )
|
||||
{
|
||||
json_value_t * pGateName = Jsonc_ObjectLookup( pJson, Node, "name" );
|
||||
json_value_t * pFanins = Jsonc_ObjectLookup( pJson, Node, "fanins" );
|
||||
json_container_t * pFanObj;
|
||||
Mio_Gate_t * pGate;
|
||||
Mio_Pin_t * pPin;
|
||||
char * pGateStr;
|
||||
if ( pGateName == NULL || pGateName->type != JSON_STRING )
|
||||
{
|
||||
printf( "Gate node %d is missing a name.\n", i );
|
||||
goto cleanup;
|
||||
}
|
||||
pGateStr = Jsonc_StringDup( pJson, *pGateName );
|
||||
if ( pGateStr == NULL )
|
||||
{
|
||||
printf( "Gate node %d has an invalid name.\n", i );
|
||||
goto cleanup;
|
||||
}
|
||||
pGate = Mio_LibraryReadGateByName( pLib, pGateStr, NULL );
|
||||
if ( pGate == NULL )
|
||||
{
|
||||
printf( "Gate \"%s\" is not found in the current library.\n", pGateStr );
|
||||
ABC_FREE( pGateStr );
|
||||
goto cleanup;
|
||||
}
|
||||
if ( pFanins == NULL || pFanins->type != JSON_OBJECT )
|
||||
{
|
||||
printf( "Gate \"%s\" is missing \"fanins\" description.\n", pGateStr );
|
||||
ABC_FREE( pGateStr );
|
||||
goto cleanup;
|
||||
}
|
||||
pFanObj = Jsonc_GetContainer( pJson, *pFanins );
|
||||
if ( pFanObj == NULL )
|
||||
{
|
||||
printf( "Gate \"%s\" has incomplete fanin information.\n", pGateStr );
|
||||
ABC_FREE( pGateStr );
|
||||
goto cleanup;
|
||||
}
|
||||
Vec_IntPush( vMapping, Mio_GateReadPinNum(pGate) );
|
||||
for ( pPin = Mio_GateReadPins(pGate), k = 0; pPin; pPin = Mio_PinReadNext(pPin), k++ )
|
||||
{
|
||||
json_value_t * pPinInfo = Jsonc_ObjectLookup( pJson, *pFanins, Mio_PinReadName(pPin) );
|
||||
json_value_t * pNodeLit;
|
||||
int NodeId, MapId;
|
||||
if ( pPinInfo == NULL || pPinInfo->type != JSON_OBJECT )
|
||||
{
|
||||
printf( "Gate \"%s\" is missing connection for pin \"%s\".\n", pGateStr, Mio_PinReadName(pPin) );
|
||||
ABC_FREE( pGateStr );
|
||||
goto cleanup;
|
||||
}
|
||||
pNodeLit = Jsonc_ObjectLookup( pJson, *pPinInfo, "node" );
|
||||
if ( pNodeLit == NULL || !Jsonc_ParseInt( pJson, *pNodeLit, &NodeId ) )
|
||||
{
|
||||
printf( "Gate \"%s\" has invalid node reference on pin \"%s\".\n", pGateStr, Mio_PinReadName(pPin) );
|
||||
ABC_FREE( pGateStr );
|
||||
goto cleanup;
|
||||
}
|
||||
if ( NodeId < 0 || NodeId >= Vec_IntSize(vNodeMap) )
|
||||
{
|
||||
printf( "Gate \"%s\" references out-of-range node %d.\n", pGateStr, NodeId );
|
||||
ABC_FREE( pGateStr );
|
||||
goto cleanup;
|
||||
}
|
||||
MapId = Vec_IntEntry( vNodeMap, NodeId );
|
||||
if ( MapId < 0 )
|
||||
{
|
||||
printf( "Gate \"%s\" refers to unsupported node %d.\n", pGateStr, NodeId );
|
||||
ABC_FREE( pGateStr );
|
||||
goto cleanup;
|
||||
}
|
||||
Vec_IntPush( vMapping, MapId );
|
||||
}
|
||||
Vec_StrPrintStr( vNames, pGateStr );
|
||||
Vec_StrPush( vNames, '\0' );
|
||||
ABC_FREE( pGateStr );
|
||||
}
|
||||
else if ( Jsonc_StringEqual( pJson, *pType, "PO" ) || Jsonc_StringEqual( pJson, *pType, "po" ) )
|
||||
{
|
||||
json_value_t * pFanin = Jsonc_ObjectLookup( pJson, Node, "fanin" );
|
||||
json_value_t * pNodeId = pFanin ? Jsonc_ObjectLookup( pJson, *pFanin, "node" ) : NULL;
|
||||
int NodeId, MapId;
|
||||
if ( pNodeId == NULL || !Jsonc_ParseInt( pJson, *pNodeId, &NodeId ) )
|
||||
{
|
||||
printf( "Primary output %d is missing driver information.\n", Vec_IntSize(vPoDrivers) );
|
||||
goto cleanup;
|
||||
}
|
||||
if ( NodeId < 0 || NodeId >= Vec_IntSize(vNodeMap) )
|
||||
{
|
||||
printf( "Primary output %d refers to out-of-range node %d.\n", Vec_IntSize(vPoDrivers), NodeId );
|
||||
goto cleanup;
|
||||
}
|
||||
MapId = Vec_IntEntry( vNodeMap, NodeId );
|
||||
if ( MapId < 0 )
|
||||
{
|
||||
printf( "Primary output %d points to unsupported node %d.\n", Vec_IntSize(vPoDrivers), NodeId );
|
||||
goto cleanup;
|
||||
}
|
||||
Vec_IntPush( vPoDrivers, MapId );
|
||||
}
|
||||
}
|
||||
if ( Vec_IntSize(vPoDrivers) != nCos )
|
||||
{
|
||||
printf( "JSONC file declares %d POs but %d drivers were found.\n", nCos, Vec_IntSize(vPoDrivers) );
|
||||
goto cleanup;
|
||||
}
|
||||
// append CO drivers
|
||||
Vec_IntForEachEntry( vPoDrivers, k, i )
|
||||
Vec_IntPush( vMapping, k );
|
||||
// append gate / CI / CO names
|
||||
Jsonc_AppendPortNames( vNames, vPiBases, vPiBits );
|
||||
Jsonc_AppendPortNames( vNames, vPoBases, vPoBits );
|
||||
// align to 4 bytes and append strings as ints
|
||||
{
|
||||
int nExtra = (4 - Vec_StrSize(vNames) % 4) % 4;
|
||||
int nWords, * pBuffer;
|
||||
for ( i = 0; i < nExtra; i++ )
|
||||
Vec_StrPush( vNames, '\0' );
|
||||
nWords = Vec_StrSize(vNames) / 4;
|
||||
pBuffer = (int *)Vec_StrArray( vNames );
|
||||
for ( i = 0; i < nWords; i++ )
|
||||
Vec_IntPush( vMapping, pBuffer[i] );
|
||||
}
|
||||
fSuccess = 1;
|
||||
cleanup:
|
||||
if ( fSuccess == 0 && ppDesignName && *ppDesignName )
|
||||
ABC_FREE( *ppDesignName );
|
||||
Vec_IntFreeP( &vPoDrivers );
|
||||
Vec_IntFreeP( &vNodeMap );
|
||||
Vec_IntFreeP( &vGateIdx );
|
||||
Vec_IntFreeP( &vPoIdx );
|
||||
Vec_IntFreeP( &vPiBits );
|
||||
Vec_IntFreeP( &vPoBits );
|
||||
if ( vNames )
|
||||
Vec_StrFree( vNames );
|
||||
if ( vPiBases )
|
||||
{
|
||||
Vec_PtrForEachEntry( char *, vPiBases, pBase, i )
|
||||
ABC_FREE( pBase );
|
||||
Vec_PtrFree( vPiBases );
|
||||
}
|
||||
if ( vPoBases )
|
||||
{
|
||||
Vec_PtrForEachEntry( char *, vPoBases, pBase, i )
|
||||
ABC_FREE( pBase );
|
||||
Vec_PtrFree( vPoBases );
|
||||
}
|
||||
if ( fSuccess == 0 && vMapping )
|
||||
{
|
||||
Vec_IntFree( vMapping );
|
||||
vMapping = NULL;
|
||||
}
|
||||
return vMapping;
|
||||
}
|
||||
Abc_Ntk_t * Jsonc_ReadNetwork( char * pFileName )
|
||||
{
|
||||
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
||||
Vec_Int_t * vMapping;
|
||||
Abc_Ntk_t * pNtk;
|
||||
char * pDesignName = NULL;
|
||||
json_t * pJson = json_create();
|
||||
if ( pJson == NULL )
|
||||
{
|
||||
printf( "Failed to allocate JSONC parser.\n" );
|
||||
return NULL;
|
||||
}
|
||||
if ( !json_load_file( pJson, pFileName ) )
|
||||
{
|
||||
printf( "Failed to load JSONC file \"%s\".\n", pFileName );
|
||||
json_destroy( pJson );
|
||||
return NULL;
|
||||
}
|
||||
vMapping = Jsonc_ConvertToMiniMapping( pJson, pLib, &pDesignName );
|
||||
json_destroy( pJson );
|
||||
if ( vMapping == NULL )
|
||||
return NULL;
|
||||
pNtk = Abc_NtkFromMiniMapping( Vec_IntArray(vMapping) );
|
||||
Vec_IntFree( vMapping );
|
||||
if ( pNtk == NULL )
|
||||
{
|
||||
ABC_FREE( pDesignName );
|
||||
return NULL;
|
||||
}
|
||||
ABC_FREE( pNtk->pName );
|
||||
pNtk->pName = pDesignName ? pDesignName : Extra_FileNameGeneric( pFileName );
|
||||
ABC_FREE( pNtk->pSpec );
|
||||
pNtk->pSpec = Abc_UtilStrsav( pFileName );
|
||||
return pNtk;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
Loading…
Reference in New Issue