iverilog/tgt-pal/fit_reg.c

133 lines
3.3 KiB
C
Raw Permalink Normal View History

2000-12-09 04:42:52 +01:00
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
2012-08-29 03:41:23 +02:00
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2000-12-09 04:42:52 +01:00
*/
# include "config.h"
2001-02-07 23:21:59 +01:00
# include "ivl_target.h"
2000-12-09 04:42:52 +01:00
# include <stdio.h>
# include <assert.h>
# include "priv.h"
2000-12-09 06:40:42 +01:00
/*
* The fit_registers function scans all the scopes for flip-flop
* devices to be assigned to macrocells. First look to see if the
* device is connected to a PAD directly or through a bufif device. If
* not, then just pick a free macrocell and drop it there.
*/
2001-05-16 05:55:30 +02:00
static int scan_ff_q(ivl_lpm_t ff, unsigned q);
2000-12-09 04:42:52 +01:00
int fit_registers(ivl_scope_t scope, void*x)
2000-12-09 04:42:52 +01:00
{
int rc;
unsigned idx;
unsigned lpms;
2000-12-09 06:40:42 +01:00
/* Scan child scopes first... */
rc = ivl_scope_children(scope, fit_registers, 0);
2000-12-09 04:42:52 +01:00
if (rc != 0)
return rc;
2000-12-09 06:40:42 +01:00
/* Scan the current scope for flip-flop devices. Pass the
devices we find to the scan_ff_q function to assign to a
macrocell. */
lpms = ivl_scope_lpms(scope);
2000-12-09 04:42:52 +01:00
for (idx = 0 ; idx < lpms ; idx += 1) {
ivl_lpm_t lpm = ivl_scope_lpm(scope, idx);
unsigned wid, q;
if (ivl_lpm_type(lpm) != IVL_LPM_FF)
continue;
wid = ivl_lpm_width(lpm);
for (q = 0 ; q < wid ; q += 1) {
2001-05-16 05:55:30 +02:00
rc = scan_ff_q(lpm, q);
2000-12-09 04:42:52 +01:00
if (rc != 0)
return rc;
}
}
return 0;
}
2000-12-09 06:40:42 +01:00
/*
* This is the part that actually assigns the single bit of a single
* flip-flop to a single macrocell.
*/
2001-05-16 05:55:30 +02:00
int scan_ff_q(ivl_lpm_t ff, unsigned q)
2000-12-09 04:42:52 +01:00
{
unsigned idx;
ivl_nexus_t nex;
2001-05-16 05:55:30 +02:00
nex = ivl_lpm_q(ff, q);
2000-12-09 04:42:52 +01:00
/* First, look to see if the Q is already connected to a pin
or an enable. If I find such a connection, then immediately
finish. */
for (idx = 0 ; idx < pins ; idx += 1) {
struct pal_bind_s*pin = bind_pin + idx;
if (pin->sop == 0)
continue;
if (pin->enable) {
if (nex == ivl_logic_pin(pin->enable, 1)) {
pin->reg = ff;
pin->reg_q = q;
return 0;
}
} else if (pin->nexus == nex) {
pin->reg = ff;
pin->reg_q = q;
return 0;
}
}
2000-12-09 06:40:42 +01:00
/* There is no pin connection, so try setting this to an
2000-12-09 04:42:52 +01:00
unbound sop cell. We know that a sop is unbound if there
are no enables, nexus or ff devices connected to it. */
for (idx = 0 ; idx < pins ; idx += 1) {
struct pal_bind_s*pin = bind_pin + idx;
if (pin->sop == 0)
continue;
if (pin->enable || pin->nexus || pin->reg)
continue;
/* Found one. Put the reg here. Leave the nexus empty so
that the code generator knows to disable the pin. */
pin->reg = ff;
pin->reg_q = q;
return 0;
}
fprintf(stderr, "No room for this ff.\n");
error_count += 1;
return 0;
}